/**
 * UI thread.
 * 
 * @author Alican Ozgoren
 * @version 12/14/2012
 */

package edu.brockport.shuttleapp;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Properties;
import java.util.Vector;

import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.support.v4.app.NotificationCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

import edu.brockport.shuttleapp.DateTimePicker;
import edu.brockport.shuttleapp.MyLocation.LocationResult;
import edu.brockport.shuttleapp.database.DatabaseInquirer;
import edu.brockport.shuttleapp.exception.UnexpectedProblemException;

public class ShuttleMainActivity extends Activity 
{
	// Database connection tool
	private Context myContext = null;
	private DatabaseInquirer myDBInquirer = null;
	
	// Activity items
	private Spinner fromSpinner;
	private Spinner toSpinner;
	private Button showDateButton;
	private TableLayout shuttleTable;
	private TextView dateTimeLabel;
	private Button fromGeolocation;
	private Button toGeolocation;
	private Button gpsButton;
	private TextView departureTitle;
	private TextView arrivalTitle;
	
	// Activity item values
	private int selectedSourceIndex;	// Initial
	private int selectedDestIndex; 	// Initial
	private boolean isShuttleAvailable;
	private String selectedTime;
	private String selectedDate;
	private String sourceStopId;
	private String destStopId;
	private Vector busStops;
	private Vector stopNames;
	private Vector availableRuns;
	private Vector mRuns;
	private Calendar lastDate;
	protected static final int START_MAP = 1;
	protected static final int START_MAP_PATH = 3;
	protected static final int START_GPS_SETTINGS = 2;
	private boolean returnedFromMap = false;
	private boolean isActivityRestarting = false;

    //----------------------------------------------------------
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shuttle_main);
        
        initUI();
	
		myContext = getApplicationContext();
		
		// Establish database connection
		establishDBConnection();
		
        // Populate spinners with the data retrieved from database
        populateSpinners();
    }

    /*@Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        getMenuInflater().inflate(R.menu.activity_shuttle_main, menu);
        return true;
    }*/
    
    //----------------------------------------------------------
    @Override
    protected void onResume() 
    {
        super.onResume();
        
        // Select the departure and arrival titles for marquee animation
       	if(arrivalTitle != null)
       		arrivalTitle.setSelected(true);
       	
       	if(departureTitle != null)
       		departureTitle.setSelected(true);
       	
       	if(isActivityRestarting && !returnedFromMap)
       	{
       		populateSpinners();
       		//Utilities.toaster(myContext, "RESTART");
       	}
       	
       	// Reset flags to default values
       	isActivityRestarting = false;
       	returnedFromMap = false;
       	
       	// Save necessary info
       	SharedPreferences settings = getSharedPreferences(Utilities.PREFS_NAME, 0);
       	checkSavedState(settings);
    }
    
    //----------------------------------------------------------
    @Override
    protected void onRestart()
    {
    	super.onRestart();
    	//populateSpinners();
    	isActivityRestarting = true;
    }
    
    //----------------------------------------------------------
    @Override
    protected void onPause()
    {
    	super.onPause();
    	
    	// Save necessary info
       	SharedPreferences settings = getSharedPreferences(Utilities.PREFS_NAME, 0);
        SharedPreferences.Editor editor = settings.edit();
        String fromSelected = (String) fromSpinner.getSelectedItem();
        String toSelected = (String) toSpinner.getSelectedItem();
        editor.putString("from", fromSelected);
        editor.putString("to", toSelected);
        editor.commit();
    }
    
    //----------------------------------------------------------
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
    	super.onActivityResult(requestCode, resultCode, data);
    	
    	if(requestCode == START_MAP || requestCode == START_MAP_PATH)
    	{
    		returnedFromMap = true;
    		//Utilities.toaster(myContext, "Returned from map!");
    	}
    }
    
    //----------------------------------------------------------
    @Override
    public void onConfigurationChanged(Configuration newConfig) 
    {
        super.onConfigurationChanged(newConfig);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
    
  	//----------------------------------------------------------
    private void checkSavedState(SharedPreferences settings)
	{
    	// Restore preferences
        String fromSelected = settings.getString("from", null);
        String toSelected = settings.getString("to", null);
        
        if(stopNames != null & fromSelected != null && toSelected != null)
        {
        	int fromIndex = stopNames.indexOf(fromSelected);
        	int toIndex = stopNames.indexOf(toSelected);
        	if(fromIndex > -1 && toIndex > -1)
        	{
        		fromSpinner.setSelection(fromIndex);
            	toSpinner.setSelection(toIndex);
        	}
        }
	}
    
    //----------------------------------------------------------
    private void establishDBConnection()
    {
    	Calendar mCal = Calendar.getInstance();
		NotificationCompat.Builder mBuilder =
	        new NotificationCompat.Builder(this)
	        .setSmallIcon(R.drawable.app_icon)
	        .setTicker("Exiting the Shuttle App...")
	        .setContentTitle("Fatal Error")
	        .setWhen(mCal.getTimeInMillis())
			.setAutoCancel(true);
		NotificationManager mNotificationManager =
				(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		
    	try
		{
			myDBInquirer = new DatabaseInquirer(myContext);
			
			if(myDBInquirer.isDatabaseIsEmpty())
	    	{
				mBuilder.setContentText("Database could not be created.");
				mNotificationManager.notify(1, mBuilder.build());
				
	    		finish();
				android.os.Process.killProcess(android.os.Process.myPid());
	    	}
		}
		catch(UnexpectedProblemException ex)
		{
			mBuilder.setContentText(ex.getMessage());
			mNotificationManager.notify(1, mBuilder.build());
			
			finish();
			android.os.Process.killProcess(android.os.Process.myPid());
		}
	
    }
    
    //----------------------------------------------------------
    private void initUI()
    {
    	// Initialize the user interface components
    	fromSpinner = (Spinner) findViewById(R.id.fromSpinner);
		toSpinner = (Spinner) findViewById(R.id.toSpinner);
		showDateButton = (Button) findViewById(R.id.showCalendar);
		shuttleTable = (TableLayout) findViewById(R.id.shuttleTable);
		dateTimeLabel = (TextView) findViewById(R.id.dateTimeLabel);
		fromGeolocation = (Button) findViewById(R.id.showFromLocation);
		toGeolocation = (Button) findViewById(R.id.showToLocation);
		gpsButton = (Button) findViewById(R.id.gpsButton);
		
		// Set the table invisible
     	setTableInvisible();
     	
     	// Set the listeners of the items
     	setListeners();
     	
    	// Set the dateTimeLabel to initial values
     	setDateTimeToCurrent();
    }
    
    // Create the activity items
    //----------------------------------------------------------
    private void setListeners()
    {
    	showDateButton.setOnClickListener(new View.OnClickListener() 
		{	
			public void onClick(View v) 
			{
				showDateTimeDialog();
			}
		});
		
		fromSpinner.setOnItemSelectedListener(getOnItemSelectedListener());
		
		toSpinner.setOnItemSelectedListener(getOnItemSelectedListener());
		
		fromGeolocation.setOnClickListener(new View.OnClickListener() 
		{	
			public void onClick(View v) 
			{
				startMapActivity("From");
			}
		});
		
		toGeolocation.setOnClickListener(new View.OnClickListener() 
		{	
			public void onClick(View v) 
			{
				startMapActivity("To");
			}
		});
		
		gpsButton.setOnClickListener(new View.OnClickListener() 
		{	
			public void onClick(View v) 
			{
				// Start a new thread to track location
				StartLocationSearch startLocationSearch = new StartLocationSearch();
				startLocationSearch.execute();
			}
		});
		
		dateTimeLabel.setOnClickListener(new View.OnClickListener() 
		{	
			public void onClick(View v) 
			{
				try 
				{
					String dateTime = (String) dateTimeLabel.getText(); 
					Properties timeAndDate = Utilities.getDateLabelTimeInDBFormat(dateTime);
					String time = timeAndDate.getProperty("Time");
					String date = timeAndDate.getProperty("Date");
					selectedDate = date;
					selectedTime = time;
					
					// Start a search thread
					StartRouteSearch startRouteSearch = new StartRouteSearch();
					startRouteSearch.execute();
				} 
				/*catch (UnexpectedProblemException e) 
				{
					// Already handled
				}*/
				catch (ParseException e) 
				{
					Utilities.toaster(myContext, "Something unexpected happened!");
				}
			}
		});
    }
    
    //----------------------------------------------------------
    private void startMapActivity(String type)
    {
    	Intent mapActivityIntent = new Intent(this, ShuttleMapActivity.class);
    	
    	String locX = null;
    	String locY = null;
    	String name = null;
    	if(type.equals("From"))
    	{
    		Properties from = (Properties) busStops.elementAt(selectedSourceIndex);
    		name = from.getProperty("name");
    		locX = from.getProperty("locationX");
    		locY = from.getProperty("locationY");
    	}
    	else
    	{
    		Properties to = (Properties) busStops.elementAt(selectedDestIndex);
    		name = to.getProperty("name");
    		locX = to.getProperty("locationX");
    		locY = to.getProperty("locationY");
    	}
    	
    	Bundle locationBundle = new Bundle();
    	locationBundle.putString("purpose", "map");
    	locationBundle.putString("name", name);
    	locationBundle.putString("X", locX);  
    	locationBundle.putString("Y", locY); 
    	mapActivityIntent.putExtras(locationBundle);
    	//startActivity(mapActivityIntent);
    	startActivityForResult(mapActivityIntent, START_MAP);
    }
    
    //----------------------------------------------------------
    private void showDateTimeDialog()
    {
    	// Create the dialog
    	final Dialog mDateTimeDialog = new Dialog(this);
    	
		// Inflate the root layout
    	LayoutInflater inflater = LayoutInflater.from(this);
		final RelativeLayout mDateTimeDialogView = 
				(RelativeLayout) inflater.inflate(R.layout.date_time_dialog, null);
		
		// Grab widget instance
		final DateTimePicker mDateTimePicker = 
				(DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
		// Check is system is set to use 24h time (this doesn't seem to work as expected though)
		final String timeS = 
				android.provider.Settings.System.getString(getContentResolver(), 
				android.provider.Settings.System.TIME_12_24);
		final boolean is24h = !(timeS == null || timeS.equals("12"));
		
		// Reload the old values if they exist
		if(lastDate != null)
		{
			mDateTimePicker.updateDate(lastDate.get(Calendar.YEAR), lastDate.get(Calendar.MONTH), 
					lastDate.get(Calendar.DAY_OF_MONTH));
			mDateTimePicker.updateTime(lastDate.get(Calendar.HOUR_OF_DAY), lastDate.get(Calendar.MINUTE));
		}
		
		// Call letTheGameBegin() when the "OK" button is clicked 
		((Button) mDateTimeDialogView.findViewById(R.id.SetDateTime)).
		setOnClickListener(new OnClickListener() 
		{
			public void onClick(View v) 
			{
				mDateTimePicker.clearFocus();
				
				selectedTime = mDateTimePicker.getTime();
				selectedDate = mDateTimePicker.getDate();
				dateTimeLabel.setText(mDateTimePicker.getDateTime());
				
				// Save date and time 
				Calendar mCal = mDateTimePicker.getCalendar();
				lastDate = Calendar.getInstance();
				lastDate.set(mCal.get(Calendar.YEAR), mCal.get(Calendar.MONTH), 
						mCal.get(Calendar.DAY_OF_MONTH), mCal.get(Calendar.HOUR_OF_DAY), mCal.get(Calendar.MINUTE));
				
				mDateTimeDialog.dismiss();
				
				// Start a search thread
				StartRouteSearch startRouteSearch = new StartRouteSearch();
				startRouteSearch.execute();
			}
		});

		// Cancel the dialog when the "Cancel" button is clicked
		((Button) mDateTimeDialogView.findViewById(R.id.CancelDialog)).
		setOnClickListener(new OnClickListener() 
		{
			public void onClick(View v) 
			{
				mDateTimeDialog.cancel();
			}
		});

		// Reset Date and Time pickers when the "Reset" button is clicked
		((Button) mDateTimeDialogView.findViewById(R.id.ResetDateTime)).
		setOnClickListener(new OnClickListener() 
		{
			public void onClick(View v) 
			{
				mDateTimePicker.reset();
			}
		});
		
		// Setup TimePicker
		mDateTimePicker.setIs24HourView(is24h);
		// No title on the dialog window
		mDateTimeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
		// Set the dialog content view
		mDateTimeDialog.setContentView(mDateTimeDialogView);
		// Display the dialog
		mDateTimeDialog.show();
	}
    
    // Start all the search/find process
    //----------------------------------------------------------
    private MyResult letTheGameBegin()
    {
    	MyResult myResult = null;
		
		// Check the shuttle availability
		isShuttleAvailable = myDBInquirer.isShuttleServiceAvailable(selectedDate);
		
		if(isShuttleAvailable)
		{
			setSourceDestStopIds();
			
			if(!isSourceDestSame())
			{
				myResult = myDBInquirer.doYourJob(sourceStopId, destStopId, selectedTime, selectedDate);
			
				return myResult;
			}
			else
			{
				myResult = new MyResult(Utilities.EQUAL_SELECTED_STOPS, null, "You need to select different stops!");
				return myResult;
			}
			
			
		}
		else // Shuttle not available on the date selected
		{
			myResult = new MyResult(Utilities.NO_SHUTTLE_AVAILABLE, null, "Campus shuttle is not operating on " + selectedDate);
			return myResult;
		}
    }
    
    // Set the dateTimeLabel to current date/time
    //----------------------------------------------------------
    private void setDateTimeToCurrent()
    {
    	DateFormat dateFormat = 
				new SimpleDateFormat("EEE, MMM d, ''yy 'at' hh:mm aaa");
    	Calendar myCalendar = Calendar.getInstance();
		dateTimeLabel.setText(dateFormat.format(myCalendar.getTime()));
    }
    
    // Populate the spinner
    //----------------------------------------------------------
    private void populateSpinners() 
    {	
    	busStops = myDBInquirer.getBusStopNames();
        
        stopNames = new Vector();
        for(int cnt = 0; cnt < busStops.size(); cnt++)
        {
        	Properties nextStop = (Properties) busStops.elementAt(cnt);
        	stopNames.add(cnt, nextStop.getProperty("name"));
        }
 
        // Creating adapter for spinners
        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, stopNames);
 
        // Drop down layout style - list view with radio button
        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
        // attaching data adapter to spinner
        fromSpinner.setAdapter(dataAdapter);
        toSpinner.setAdapter(dataAdapter);
        toSpinner.setSelection(6, true);
    }
    
    // Refresh the spinner
    //----------------------------------------------------------
    private void refreshSpinners() 
    {	
        stopNames = new Vector();
        for(int cnt = 0; cnt < busStops.size(); cnt++)
        {
        	Properties nextStop = (Properties) busStops.elementAt(cnt);
        	stopNames.add(cnt, nextStop.getProperty("name"));
        }
 
        // Creating adapter for spinners
        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, stopNames);
 
        // Drop down layout style - list view with radio button
        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
        // attaching data adapter to spinner
        fromSpinner.setAdapter(dataAdapter);
        toSpinner.setAdapter(dataAdapter);
        toSpinner.setSelection(6, true);
    }
    
    //----------------------------------------------------------
    private void setSourceDestStopIds()
    {
    	Properties source = (Properties) busStops.elementAt(selectedSourceIndex);
    	Properties destination = (Properties) busStops.elementAt(selectedDestIndex);
    	
    	sourceStopId = source.getProperty("_id");
    	destStopId = destination.getProperty("_id");
    }
    
    //----------------------------------------------------------
    private boolean isSourceDestSame()
    {
    	if(sourceStopId.compareTo(destStopId) == 0)
    		return true;
    	
    	return false;
    }
    
    //----------------------------------------------------------
    private void setTableInvisible()
    {
    	int childCount = shuttleTable.getChildCount();
    	
    	for(int cnt = 0; cnt < childCount; cnt++)
    	{
    		View nextRow = shuttleTable.getChildAt(cnt);
    		nextRow.setVisibility(4);
    	}
    }
    
    //----------------------------------------------------------
    private MyResult populateTable()
    {	
    	// Put all the cells into a list
    	Vector textViewList = new Vector();
    	
    	// Get the selected stop names
    	Properties source = (Properties) busStops.elementAt(selectedSourceIndex);
    	Properties destination = (Properties) busStops.elementAt(selectedDestIndex);
    	String departure = source.getProperty("name");
    	String arrival = destination.getProperty("name");
    	
    	TableRow titleRow = (TableRow) shuttleTable.getChildAt(0);
    	TextView routeTitle = (TextView) titleRow.getChildAt(0);
    	routeTitle.setText("RT");
    	departureTitle = (TextView) titleRow.getChildAt(1);
    	departureTitle.setText(departure);
    	departureTitle.setSelected(true);
    	arrivalTitle = (TextView) titleRow.getChildAt(2);
    	arrivalTitle.setText(arrival);
    	arrivalTitle.setSelected(true);
    	
    	for(int cnt = 1; cnt < shuttleTable.getChildCount(); cnt++)
    	{
    		TableRow nextRow = (TableRow) shuttleTable.getChildAt(cnt);
    		nextRow.setClickable(true);
    		nextRow.setOnClickListener(getTableRowOnClickListener());
    		for(int rowCnt = 0; rowCnt < nextRow.getChildCount(); rowCnt++)
    		{
    			TextView nextCell = (TextView) nextRow.getChildAt(rowCnt);
    			textViewList.add(nextCell);
    		}
    	}
    	
    	// Iterate through the available run list, and add 
    	// the values into the cells retrieved above
    	int textViewCounter = 0;
    	for(int cnt = 0; cnt < availableRuns.size(); cnt++)
    	{
    		Properties nextRun = (Properties) availableRuns.elementAt(cnt);
    		String route = nextRun.getProperty("Route");
    		String departureTime = nextRun.getProperty("DepartureTime");
    		String arrivalTime = nextRun.getProperty("ArrivalTime");
    		
    		// Convert times
    		MyResult myResult = Utilities.convertDBTimeTo12HourFormat(myContext, departureTime);
        	int resultCode = myResult.getResultCode();
        	Vector resultList = null;
        	if(resultCode != Utilities.NO_ERROR)
        	{
        		myResult = new MyResult(resultCode, null, myResult.getResultMessage());
        		return myResult;
        	}
        	else
        	{
        		resultList = myResult.getResult();
        		departureTime = (String) resultList.elementAt(0);
        	}
        	
        	myResult = Utilities.convertDBTimeTo12HourFormat(myContext, arrivalTime);;
        	resultCode = myResult.getResultCode();
        	if(resultCode != Utilities.NO_ERROR)
        	{
        		myResult = new MyResult(resultCode, null, myResult.getResultMessage());
        		return myResult;
        	}
        	else
        	{
        		resultList = myResult.getResult();
        		arrivalTime = (String) resultList.elementAt(0);
        	}
    		
    		do
    		{
    			TextView nextTextView = (TextView) textViewList.elementAt(textViewCounter);
    			
    			if((textViewCounter + 1) % 3 == 1) // first iteration
    				nextTextView.setText(route);
    			else
    			if((textViewCounter + 1) % 3 == 2) // second iteration
    				nextTextView.setText(departureTime);
    			else
    			if((textViewCounter + 1) % 3 == 0) // third iteration
    				nextTextView.setText(arrivalTime);
    			
    			textViewCounter++;
    		}while((textViewCounter) % 3 != 0 && textViewCounter < textViewList.size() + 1);
    	}
    	
    	// Set the visibility of the rows according to run count
    	for(int cnt = 0; cnt < availableRuns.size() + 1; cnt++)
    	{
    		TableRow nextRow = (TableRow) shuttleTable.getChildAt(cnt);
    		nextRow.setVisibility(1);
    	}
    	
    	return new MyResult(Utilities.NO_ERROR, null, null);
    }
    
    //----------------------------------------------------------
    private OnClickListener getTableRowOnClickListener()
    {
    	OnClickListener tableRowListener = new OnClickListener()
    	{
			@Override
			public void onClick(View v) 
			{
				int mRunSize = mRuns.size();
				String mRunId = (String) mRuns.elementAt(0); 
				if(v.equals(shuttleTable.getChildAt(2)) && mRunSize > 1)
				{
					mRunId = (String) mRuns.elementAt(1); 
				}
				else
				if(v.equals(shuttleTable.getChildAt(3)) && mRunSize > 2)
				{
					mRunId = (String) mRuns.elementAt(2); 
				}

				// Start a MapActivity
				StartMapViewToShowPath startMapViewToShowPath = new StartMapViewToShowPath();
				startMapViewToShowPath.execute(new String[] { mRunId });
			}
    	};
    	
    	return tableRowListener;
    }
    
    //----------------------------------------------------------
    private boolean showStopsOnMap(String runId)
    {
    	Vector<Properties> routeInfo = myDBInquirer.getRouteInfo(runId);
    	boolean statusOK;
    	
    	if(routeInfo != null && routeInfo.size() > 0)
    	{
    		Intent showPathOnMapActivityIntent = new Intent(this, ShuttleMapActivity.class);
    
    		Bundle pathBundle = new Bundle();
    		pathBundle.putString("purpose", "path");
    		for(int cnt = 0; cnt < routeInfo.size(); cnt++)
    		{
    			Properties nextRow = routeInfo.elementAt(cnt);
    			String x = nextRow.getProperty("locationX");
    			String y = nextRow.getProperty("locationY");
    			String name = nextRow.getProperty("name");
    			String seq = nextRow.getProperty("Sequence");
    			String selected = "";
    			String departure = "";
    			
    			if(name.equals(departureTitle.getText()) || 
    			   name.equals(arrivalTitle.getText()))
    				selected = "true";

    			else
    				selected = "false";
    			
    			
    			if(name.equals(departureTitle.getText()))
    				departure = "true";
    			
    			else
    				departure = "false";
    			
    			
    			// Put info into pathBundle
    			pathBundle.putString(seq, name + ";" + x + ";" + y + ";" + selected + ";" + departure);  
    		}
    		// Put pathBundle into the intent
    		showPathOnMapActivityIntent.putExtras(pathBundle);
    		startActivityForResult(showPathOnMapActivityIntent, START_MAP_PATH);
    		statusOK = true;
    	}
    	else
    	{
    		Utilities.toaster(myContext, "Unexpected problem!");
    		statusOK = false;
    	}
    	
    	return statusOK;
    }
    
    //----------------------------------------------------------
    private OnItemSelectedListener getOnItemSelectedListener()
    {
    	OnItemSelectedListener listener = new OnItemSelectedListener() 
		{
		    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) 
		    {
		    	if(((Spinner) parent).getId() == R.id.fromSpinner)
		    		selectedSourceIndex = parent.getSelectedItemPosition();
		    	else
		    	if(((Spinner) parent).getId() == R.id.toSpinner)
		    		selectedDestIndex = parent.getSelectedItemPosition();
		    	
		    	String blah = toSpinner.getSelectedItem().toString();
		    	String bloh = fromSpinner.getSelectedItem().toString();
		    	
		    	if(blah.equals(bloh))
		    		Utilities.toaster(myContext, "We need different stops to process your request!");
		    }
			
		    public void onNothingSelected(AdapterView<?> parent) 
		    {
		    }
		};
		
		return listener;
    }
    
    //----------------------------------------------------------
    public void switchStartStop(View v) 
	{
    	// Disable listeners
    	fromSpinner.setOnItemSelectedListener(null);
    	toSpinner.setOnItemSelectedListener(null);
        
    	// Switch data
    	String fromSelected = (String) fromSpinner.getSelectedItem();
        String toSelected = (String) toSpinner.getSelectedItem();
        int fromIndex = ((ArrayAdapter) fromSpinner.getAdapter()).getPosition(fromSelected);
        int toIndex = ((ArrayAdapter) toSpinner.getAdapter()).getPosition(toSelected);
        fromSpinner.setSelection(toIndex);
        toSpinner.setSelection(fromIndex);
        
        // Set listeners again
        fromSpinner.setOnItemSelectedListener(getOnItemSelectedListener());
        toSpinner.setOnItemSelectedListener(getOnItemSelectedListener());
        
        Utilities.toaster(myContext, "We switched the stops for you!");
    } 
    
    //----------------------------------------------------------
    public void sortSpinners(View v)
    {
    	populateSpinners();
    	Utilities.toaster(myContext, "We sorted the bus stops alphabetically for you!");
    }
    
    //----------------------------------------------------------
    private class StartMapViewToShowPath extends AsyncTask<String, Void, Boolean> 
    {
    	ProgressDialog dialog;
    	
        //----------------------------------------------------------
        @Override
        protected Boolean doInBackground(String... routes) 
        {
        	Boolean status = Boolean.valueOf(false);
        	for(String runId: routes)
        		status = Boolean.valueOf(showStopsOnMap(runId));
        	
        	return status;
        }

        //----------------------------------------------------------
        @Override
        protected void onPostExecute(Boolean result) 
        {
        	dialog.dismiss();
        	
        	if(!result.booleanValue())
        		Utilities.toaster(myContext, "Unexpected problem!");
        }
        
        //----------------------------------------------------------
        @Override
        protected void onPreExecute()
        {
            dialog = ProgressDialog.show(ShuttleMainActivity.this, "Please wait", 
                    "We are creating the map...", true);
        }  
    }
    
    //----------------------------------------------------------
    private class StartRouteSearch extends AsyncTask<Void, Void, MyResult> 
    {
    	ProgressDialog dialog;
    	
        //----------------------------------------------------------
        @Override
        protected MyResult doInBackground(Void... voids) 
        {
        	return letTheGameBegin();
        }

        //----------------------------------------------------------
        @Override
        protected void onPostExecute(MyResult myResult) 
        {
        	dialog.dismiss();
        	
        	int resultCode = myResult.getResultCode();
        	if(resultCode != Utilities.NO_ERROR)
        	{
        		Utilities.longToaster(myContext, myResult.getResultMessage());
        	}
        	else
        	{
        		availableRuns = myResult.getResult();
        		if(availableRuns != null && availableRuns.size() > 0)
    			{
        			String successMsg = myResult.getResultMessage();
    				MyResult result = populateTable();
    				resultCode = result.getResultCode();
    				if(resultCode != Utilities.NO_ERROR)
    					Utilities.toaster(myContext, myResult.getResultMessage());
    				else
    				{
    					mRuns = new Vector();
    					for(int cnt = 0; cnt < availableRuns.size(); cnt++)
    					{
    						Properties run = (Properties) availableRuns.elementAt(cnt);
    						String runId = run.getProperty("RunId");
    						mRuns.add(cnt, runId);
    					}
    					
    					Utilities.toaster(myContext, successMsg);
    				}
    			}
        		else
        		{
        			Utilities.toaster(myContext, "Shuttle is not available at the selected time.");
        		}
        	}
        }
        
        //----------------------------------------------------------
        @Override
        protected void onPreExecute()
        {
        	// Make the table Invisible
        	setTableInvisible();
        	// Start the process, show a dialog first
            dialog = ProgressDialog.show(ShuttleMainActivity.this, "Please wait", 
                    "We are getting the available routes...", true);
        }  
    }
    
    //----------------------------------------------------------
    private class StartLocationSearch extends AsyncTask<Void, Void, MyResult> 
    {
    	private ProgressDialog dialog;
    	private volatile MyLocation myLocation;
    	private volatile MyResult locDisabledResult;
    	private volatile Location currentLocation;
    	private volatile boolean dialogCancelled = false;
    	private LocationResult locationResult = new LocationResult()
    	{
		    @Override
		    public void gotLocation(Location location)
		    {
		        //Got the location!
		    	//Log.v("LAT-1", Double.toString(location.getLatitude()));
		    	//Log.v("LONG-1", Double.toString(location.getLongitude()));
		    	//int lat = (int) (location.getLatitude() * 1E6);
		        //int lng = (int) (location.getLongitude() * 1E6);
		        //Log.v("LAT-2", Integer.toString(lat));
		    	//Log.v("LONG-2", Integer.toString(lng));
		    	currentLocation = location;
		    	
		    }
		};
    	
	    //----------------------------------------------------------
        @Override
        protected MyResult doInBackground(Void... voids) 
        {	
        	if(!isCancelled())
        	{
        		//myLocation.startTrackingLocation();
        		try 
        		{
        			// Wait 5 seconds to get accurate location data
					Thread.sleep(5000);
				} 
        		catch (InterruptedException e) 
				{
        			// If the thread is interrupted somehow, inform user that task was failed
        			return new MyResult(Utilities.UNEXPECTED_ERROR, null, "Sorry, we could not track your location.");
				}
        		
        		// Everything went well, get the location data. 
        		// But first check the update result
        		Vector resultList = new Vector();
        		if(currentLocation != null)
        		{
        			resultList.add(currentLocation);
            		return new MyResult(Utilities.NO_ERROR, resultList, "There it is! We set the source stop for you!");
        		}
        		else // Check for latest saved data
        		{
        			myLocation.lookForAccurateData();
        			if(currentLocation != null)
            		{
            			resultList.add(currentLocation);
                		return new MyResult(Utilities.NO_ERROR, resultList, 
                				"We found an old location data. Please be aware that the old " +
                				"location data may not be accurate.");
            		}
        		}	
        	}

        	return null;
        }

        //----------------------------------------------------------
        @Override
        protected void onPostExecute(MyResult myResult) 
        {
        	dialog.dismiss();
        	
        	if(myResult != null)
        	{
        		int resultCode = myResult.getResultCode();
            	if(resultCode != Utilities.NO_ERROR)
            	{
            		Utilities.toaster(myContext, myResult.getResultMessage());
            	}
            	else
            	{
            		String resultMessage = myResult.getResultMessage();
            		Vector resultList = myResult.getResult();
            		Location currentLocation = (Location) resultList.elementAt(0);
            		busStops = myDBInquirer.getBusStopNames(currentLocation);
            		refreshSpinners();
    
            		if(resultMessage.startsWith("There it is"))
        				Utilities.longToaster(myContext, resultMessage);
        			
        			else
        				Utilities.longToaster(myContext, resultMessage);
            	}
        	}
        }
        
        //----------------------------------------------------------
        @Override
        protected void onPreExecute()
        {
        	// Start the process, show a dialog first
            dialog = ProgressDialog.show(ShuttleMainActivity.this, "Please wait", 
                    "We are tracking your current location...", true, true, createOnCancelListener());
            myLocation = new MyLocation(ShuttleMainActivity.this, locationResult);
        	MyResult myResult = myLocation.checkServices();
        	int resultCode = myResult.getResultCode();
        		
        	if(resultCode != Utilities.NO_ERROR)	
        	{
        		if(resultCode == Utilities.LOCATION_DISABLED)
        		{
        			locDisabledResult = myResult;
        		}
        		cancel(true);
        	}
        	else
        	{
        		myLocation.requestLocationUpdates();
        	}
        }  
        
        //----------------------------------------------------------
        @Override
        protected void onCancelled() 
        {
        	dialog.dismiss();
        	if(locDisabledResult != null)
    		{
    			String msg = locDisabledResult.getResultMessage();
    			String title = "Houston, we have a problem!";
    			AlertDialog.Builder alertDialogBuilder = new Builder(ShuttleMainActivity.this);
    			alertDialogBuilder
    				.setTitle(title)
    				.setMessage(msg)
    				.setCancelable(false)
    				.setPositiveButton("Turn on GPS", new DialogInterface.OnClickListener() 
    				{
    					public void onClick(DialogInterface dialog, int id) 
    					{
    						ShuttleMainActivity.this.startActivityForResult(
    								new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), 
    								ShuttleMainActivity.START_GPS_SETTINGS);
    					}
    				})
    				.setNegativeButton("No, keep it off",new DialogInterface.OnClickListener() 
    				{
    					public void onClick(DialogInterface dialog, int id) 
    					{
    						
    						dialog.cancel();
    					}
    				});
    			
    			AlertDialog alertDialog = alertDialogBuilder.create();
    			alertDialog.show();	
    		}
        	else if(!dialogCancelled)
        	{
        		Utilities.toaster(myContext, "Unexpected error!");
        	}
        }
        
        //----------------------------------------------------------
        private OnCancelListener createOnCancelListener()
        {
        	OnCancelListener cancelListener = new OnCancelListener() 
        	{
        		@Override
                public void onCancel(DialogInterface dialog) 
        		{
        			dialogCancelled = true;
                    cancel(true);
                }
            };   
            return cancelListener;
        }
    }
}
